package com.edroid.droidhelper.pc.util;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SignatureException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

/**
 * 封装一个MD5算法.包含16位与32位
 * @author Simon.Zhu
 *
 */
final public class CmmnDecode {
	static String inputCharset = "utf8";
	private CmmnDecode () {}
	
	private static final char[] Digit = 
	{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
	
	private static String byteHEX(byte ib) {
		char[] ob = new char[2];
		ob[0] = Digit[(ib >>> 4) & 0x0F];
		ob[1] = Digit[ ib & 0x0F ];
		return new String(ob);
    }
	
	private static String to32(byte[] md5Bytes) {
        String digestHexStr = "";
        for (int i = 0; i < 16; i++) {
            digestHexStr += byteHEX(md5Bytes[i]);
        }
        return digestHexStr;
    }
	
	public static byte[] md5_16(String str) {
		byte[] res = null;
		MessageDigest md5 = null;
		try {
			md5 = MessageDigest.getInstance("MD5");
		}catch (NoSuchAlgorithmException ex) {}
		try {
			res = md5.digest(str.getBytes("utf-8"));
		} catch (UnsupportedEncodingException e) {}
		return res;
	}
	
    public static String md5_32(String str) {
		byte[] res = md5_16(str);
		return to32(res);
	}
    
    /**
     * 对称解密算法
     * @param s
     * @param key1
     * @param key2
     * @return
     */
    public static String decrypt(String s, int key1, int key2) {
    	
    	
		String str = "";
		try {
			//base64解密
			//String code = Base64.decode(s);
				
			String code = s;
				
//			if (code.length() % 2 != 0) {
//				return null;
//			}
			StringBuffer sb = new StringBuffer(code);
			ByteBuffer bb = ByteBuffer.allocate(code.length() / 2);

			int i = 0;
			while (i < code.length()) {
				bb.put((byte) ((Integer.parseInt(sb.substring(i, i + 1), 16)) << 4 | Integer
						.parseInt(sb.substring(i + 1, i + 2), 16)));
				i = i + 2;
			}
			
			byte cCode[] = bb.array();
			
			for (i = 0; i < cCode.length; i++) {
				if (i == cCode.length - 1) {
					cCode[cCode.length - 1] ^= (key2 % 128);
				} else if (cCode[i] != cCode[i + 1]) {
					cCode[i] ^= cCode[i + 1];
				}
			}
			for (i = cCode.length - 1; i >= 0; i--) {
				if (i == 0) {
					cCode[0] ^= (key1 % 128);
				} else if (cCode[i] != cCode[i - 1]) {
					cCode[i] ^= cCode[i - 1];
				}
			}
			
			str = new String(cCode, "UTF-8");
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
		
		return str;
	}
    
    
	private static String Md5(String id) {
		
		String result = "";
		byte[] args = null;
		
		try {
			// 生成MessageDigest对象,传入所用算法的参数(MD5)
			MessageDigest messageDigest = MessageDigest.getInstance("MD5");
			// 使用 getBytes( )方法生成字符串数组
			messageDigest.update(id.getBytes("UTF-8"));
			// 执行MessageDigest对象的digest( )方法完成计算，计算的结果通过字节类型的数组返回
			args = messageDigest.digest();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException ee) {
			ee.printStackTrace();
		}

		try {
			// 将结果转换成字符串
			result = "";// result清空，否则它会自动累加！！！
			for (int i = 0; i < args.length; i++) {
				result += Integer.toHexString((0x000000ff & args[i]) | 0xffffff00)
						.substring(6);
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return result;
	}

	/**
	 *  MD5对比
	 * @param s1
	 * @param s2
	 * @return
	 */
	public static boolean checkCode(String s1, String s2) {
		return s2.equals(Md5(s1));
	}
	
	/**
	 * 加密算法
	 * 
	 * @throws IOException
	 * @throws FileNotFoundException
	 */
	public static String createSekey(Map<String, String> sArray) {
		String securekey = "@#$123dsafrfr12";
		String sekey;
		String formatUri = createLinkString(paraFilter(sArray));
		formatUri = formatUri + "&save=" + securekey;
//		System.out.println(formatUri);
		sekey = Md5(formatUri);
		return sekey;
	}

	/**
	 * 除去数组中的空值和签名参数
	 * 
	 * @param sArray
	 *            签名参数组
	 * @return 去掉空值与签名参数后的新签名参数组
	 */
	public static Map<String, String> paraFilter(Map<String, String> sArray) {

		Map<String, String> result = new HashMap<String, String>();

		if (sArray == null || sArray.size() <= 0) {
			return result;
		}
		for (String key : sArray.keySet()) {
			String value = sArray.get(key);
			if (value == null || key.equalsIgnoreCase("sekey")) {
				continue;
			}
			result.put(key, value);
		}
		return result;
	}

	/**
	 * 把数组所有元素排序，并按照“参数=参数值”的模式用“&”字符拼接成字符串
	 * 
	 * @param params
	 *            需要排序并参与字符拼接的参数组
	 * @return 拼接后字符串
	 */
	public static String createLinkString(Map<String, String> params) {

		ArrayList<String> keys = new ArrayList<String>(params.keySet());
		Collections.sort(keys);
		String prestr = "";

		for (int i = 0; i < keys.size(); i++) {
			String key = keys.get(i);
			String value = params.get(key);
			if (i == keys.size() - 1) { // 拼接时，不包括最后一个&字符
				prestr = prestr + key + "=" + value;
			} else {
				prestr = prestr + key + "=" + value + "&";
			}
		}
		return prestr;
	}

	/**
	 * 
	 * 
	 * @param s
	 * @param k1
	 * @param k2
	 * @return
	 */
	public static String encrypt(String s, int k1, int k2) {
		//int strLen = s.length();
		//char[] _s = s.toCharArray();
		byte[] _s = s.getBytes();
		int strLen = _s.length;
		
		int i = 0;
		
		for (i = 0; i < strLen; i++) {
			if (0 == i) {
				_s[0] ^= (k1 % 128);
			} else if (_s[i] != _s[i - 1]) {
				_s[i] ^= _s[i - 1];
			}
		}
		
		int j = strLen - 1;
		for (i = j; i > -1; i--) {
			if (i == j) {
				_s[i] ^= (k2 % 128);
			} else if (_s[i] != _s[i + 1]) {
				_s[i] ^= _s[i + 1];
			}
		}
		
		
		String result = "";
		for (i = 0; i < strLen; i++) {
			
			result += Integer.toHexString((0x000000ff & _s[i]) | 0xffffff00)
					.substring(6);			
		}
		return result;
	}
	
	public static void main(String[] args) {
		String src = "12345678";
		
		String dst = encrypt(src, 1024, 1025);
		
		System.out.println(dst);
		
		System.out.println(decrypt(dst, 1024, 1025));
		
	}
}

